#coding:utf-8
# 导入兼容性补丁以解决Python 3.10+中的collections.Callable问题
from app.compat import *
import os
import sys
import importlib.util
from flask import Flask, redirect, url_for, request
from datetime import datetime
from flask_bootstrap import Bootstrap

# 动态加载config_default.py
if getattr(sys, 'frozen', False):
    # 打包后的环境，从外部app文件夹加载
    config_default_path = os.path.join(os.path.dirname(sys.executable),  'config_default.py')
    if os.path.exists(config_default_path):
        spec = importlib.util.spec_from_file_location("config_default", config_default_path)
        config_default_module = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(config_default_module)
        DefaultConfig = config_default_module.Config
    else:
        # 如果外部文件不存在，使用默认配置
        class DefaultConfig(object):
            DEBUG = False
            SECRET_KEY = 'this is secret string'
            SQLALCHEMY_COMMIT_ON_TEARDOWN = True
            SQLALCHEMY_TRACK_MODIFICATIONS = False
            CATALOG_DEEP = 3
            ERROR_LOG = "../logs/error.log"
            INFO_LOG = "../logs/info.log"
            DB_PREFIX = "bb_"
            PER_PAGE = 20
            STATIC_IMG_PATH = "img"
            AVATAR_PATH = "resource/image/avatar"
            TMP_PATH = "resource/tmp"
            IMAGE_PATH = "resource/image/image"
            BOOK_COVER_PATH = "resource/image/cover"
else:
    # 开发环境，直接导入
    from app.config_default import Config as DefaultConfig


bootstrap = Bootstrap()

def check_start(app, db):
    from app.includes.start import _exist_config, exist_table, load_site, create_path
    create_path(app)
    app.start = False
    if _exist_config(app):
        # 在打包环境中，从外部app文件夹导入config.py
        if getattr(sys, 'frozen', False):
            config_path = os.path.join(os.path.dirname(sys.executable),  'config.py')
            spec = importlib.util.spec_from_file_location("config", config_path)
            config_module = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(config_module)
            app.config.from_object(config_module.Config)
        else:
            # 开发环境，从app.config导入
            from app.config import Config
            app.config.from_object(Config)
        if exist_table(app):
            load_site(app)
            app.start = True
            return
    @app.before_request
    def request_check_start():
        if app.start:
            return
        ends = frozenset(["admin.setup", "admin.install", "static"])
        if request.endpoint in ends:
            return
        if not _exist_config(app):
            return redirect(url_for("admin.setup"))
        return redirect(url_for("admin.install"))


def template_filters(app):
    @app.template_filter("friendly_time")
    def friendly_time(date):
        now = datetime.now()
        delta = now - date
        if delta.days >= 365:
            return u'%d年前' % (delta.days / 365)
        elif delta.days >= 30:
            return u'%d个月前' % (delta.days / 30)
        elif delta.days > 0:
            return u'%d天前' % delta.days
        elif delta.days < 0:
            return u"0秒前"
        elif delta.seconds < 60:
            return u"%d秒前" % delta.seconds
        elif delta.seconds < 60 * 60:
            return u"%d分钟前" % (delta.seconds / 60)
        else:
            return u"%d小时前" % (delta.seconds / 60 / 60)


def create_app():
    # 检测是否在PyInstaller打包环境中运行
    if getattr(sys, 'frozen', False):
        # 打包后的环境，使用sys.executable所在目录作为基础路径
        base_path = os.path.dirname(sys.executable)
        template_folder = os.path.join(base_path, 'templates')
        static_folder = os.path.join(base_path, 'static')
        
        # 初始化Flask应用，使用主要模板目录
        app = Flask(
            __name__, 
            template_folder=template_folder,
            static_folder=static_folder
        )
        
        # 添加额外的模板搜索路径以确保能找到Bootstrap模板
        # 在PyInstaller环境中，我们不能依赖os.path.exists检查，因为文件可能在archive中
        extra_template_paths = [
            # 尝试添加flask_bootstrap包中的模板目录
            os.path.join(os.path.dirname(sys.executable), 'lib', 'site-packages', 'flask_bootstrap', 'templates'),
            os.path.join(os.path.dirname(sys.executable), 'flask_bootstrap', 'templates'),
            # 尝试添加相对路径
            os.path.join(base_path, 'lib', 'site-packages', 'flask_bootstrap', 'templates'),
            os.path.join(base_path, 'flask_bootstrap', 'templates'),
            # 添加一个更通用的路径，直接指向templates目录
            os.path.join(base_path, 'templates')
        ]
        
        # 将额外的模板路径添加到Jinja的搜索路径中
        # 在PyInstaller环境中，我们不能依赖os.path.exists检查
        for path in extra_template_paths:
            if path not in app.jinja_loader.searchpath:
                app.jinja_loader.searchpath.append(path)
        
        # 确保Bootstrap的模板目录被添加到搜索路径中
        # 使用Flask-Bootstrap提供的方法来获取正确的模板路径
        try:
            import flask_bootstrap
            bootstrap_path = os.path.join(os.path.dirname(flask_bootstrap.__file__), 'templates')
            if bootstrap_path not in app.jinja_loader.searchpath:
                app.jinja_loader.searchpath.append(bootstrap_path)
        except Exception as e:
            # 如果无法获取flask_bootstrap的路径，至少记录错误
            import logging
            logging.warning(f"Failed to get flask_bootstrap template path: {e}")
    else:
        # 开发环境，使用默认路径
        app = Flask(__name__)
    app.config.from_object(DefaultConfig)

    # 添加is_xhr属性以兼容旧代码
    @app.before_request
    def add_is_xhr_attribute():
        request.is_xhr = request.headers.get('X-Requested-With') == 'XMLHttpRequest'

    from app.models.model import db, login_manager

    bootstrap.init_app(app)
    db.init_app(app)
    db.PREFIX = app.config["DB_PREFIX"]

    app.site = {}
    def site_context_processor():
        return dict(site=app.site)
    app.context_processor(site_context_processor)
    check_start(app, db)

    login_manager.init_app(app)

    from app.web import web
    app.register_blueprint(web)

    from app.admin import admin
    app.register_blueprint(admin, url_prefix="/admin")

    from app.api import api
    app.register_blueprint(api, url_prefix="/api")

    template_filters(app)

    login_manager.login_view = "admin.login"
    login_manager.login_message = "请先登录!!!"

    # 在打包环境中，从外部app文件夹导入log.py
    if getattr(sys, 'frozen', False):
        log_path = os.path.join(os.path.dirname(sys.executable), 'log.py')
        if os.path.exists(log_path):
            try:
                spec = importlib.util.spec_from_file_location("log", log_path)
                log_module = importlib.util.module_from_spec(spec)
                spec.loader.exec_module(log_module)
                log_module.init_logging(app)
            except Exception as e:
                # 如果无法导入外部log.py，使用内置的日志初始化
                import logging
                logging.basicConfig(level=logging.DEBUG)
                logging.warning(f"Failed to import external log.py: {e}")
        else:
            # 如果外部log.py不存在，使用内置的日志初始化
            import logging
            logging.basicConfig(level=logging.DEBUG)
    else:
        # 开发环境，直接导入
        from app.log import init_logging
        init_logging(app)

    return app


